001 /* 002 * Copyright 2004 Niclas Hedhman 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 013 * implied. 014 * 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package net.dpml.util; 019 020 import java.util.Enumeration; 021 import java.util.Properties; 022 import java.util.Stack; 023 import java.util.StringTokenizer; 024 025 import net.dpml.transit.Transit; 026 027 /** 028 * Utility class that handles substitution of property names in the string 029 * for ${value} relative to a supplied set of properties. 030 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 031 * @version 1.0.1 032 */ 033 public final class PropertyResolver 034 { 035 // ------------------------------------------------------------------------ 036 // static 037 // ------------------------------------------------------------------------ 038 039 static 040 { 041 Object xx = Transit.DPML_DATA; 042 } 043 044 /** 045 * System property symbol substitution from properties. 046 * Replace any occurances of ${[key]} with the value of the property 047 * assigned to the [key] in the system properties. 048 * @param value a string containing possibly multiple ${[value]} sequences 049 * @return the expanded string 050 */ 051 public static String resolve( String value ) 052 { 053 Properties properties = System.getProperties(); 054 return resolve( properties, value ); 055 } 056 057 /** 058 * System property symbol substitution from properties. 059 * Replace any occurances of ${[key]} with the value of the property 060 * assigned to the [key] in the system properties or supplied properties. 061 * @param properties an arbitary properties file containing unresolved properties 062 * @return the property file with expended properties 063 */ 064 public static Properties resolve( Properties properties ) 065 { 066 Properties system = System.getProperties(); 067 Enumeration names = properties.propertyNames(); 068 while( names.hasMoreElements() ) 069 { 070 String name = (String) names.nextElement(); 071 String old = properties.getProperty( name ); 072 String value = resolve( old ); 073 String v2 = resolve( properties, value ); 074 if( !v2.equals( old ) ) 075 { 076 properties.setProperty( name, v2 ); 077 } 078 } 079 return properties; 080 } 081 082 /** 083 * Symbol substitution from properties. 084 * Replace any occurances of ${[key]} with the value of the property 085 * assigned to the [key] in the supplied properties argument. 086 * @param props the source properties from which substitution is resolved 087 * @param value a string containing possibly multiple ${[value]} sequences 088 * @return the expanded string 089 */ 090 public static String resolve( Properties props, String value ) 091 { 092 if( value == null ) 093 { 094 return null; 095 } 096 097 // optimization for common case. 098 if( value.indexOf( '$' ) < 0 ) 099 { 100 return value; 101 } 102 int pos1 = value.indexOf( "${" ); 103 if( pos1 < 0 ) 104 { 105 return value; 106 } 107 108 Stack stack = new Stack(); 109 StringTokenizer st = new StringTokenizer( value, "${}", true ); 110 111 while ( st.hasMoreTokens() ) 112 { 113 String token = st.nextToken(); 114 115 if( token.equals( "}" ) ) 116 { 117 String name = (String) stack.pop(); 118 String open = (String) stack.pop(); 119 if( open.equals( "${" ) ) 120 { 121 String propValue = System.getProperty( name ); 122 if( propValue == null ) 123 { 124 propValue = props.getProperty( name ); 125 } 126 if( propValue == null ) 127 { 128 push( stack, "${" + name + "}" ); 129 } 130 else 131 { 132 push( stack, propValue ); 133 } 134 } 135 else 136 { 137 push( stack, "${" + name + "}" ); 138 } 139 } 140 else 141 { 142 if( token.equals( "$" ) ) 143 { 144 stack.push( "$" ); 145 } 146 else 147 { 148 push( stack, token ); 149 } 150 } 151 } 152 String result = ""; 153 while ( stack.size() > 0 ) 154 { 155 result = stack.pop() + result; 156 } 157 return result; 158 } 159 160 /** 161 * Pushes a value on a stack 162 * @param stack the stack 163 * @param value the value 164 */ 165 private static void push( Stack stack , String value ) 166 { 167 if( stack.size() > 0 ) 168 { 169 String data = (String) stack.pop(); 170 if( data.equals( "${" ) ) 171 { 172 stack.push( data ); 173 stack.push( value ); 174 } 175 else 176 { 177 stack.push( data + value ); 178 } 179 } 180 else 181 { 182 stack.push( value ); 183 } 184 } 185 186 // ------------------------------------------------------------------------ 187 // constructor 188 // ------------------------------------------------------------------------ 189 190 /** 191 * Null constructor. 192 */ 193 private PropertyResolver() 194 { 195 } 196 } 197